<?php declare(strict_types=1);

namespace shali\ydb\think2fa\service;

use app\common\model\agent\Agent;
use shali\ydb\think2fa\facade\TwoFactorAuth;
use shali\ydb\think2fa\model\Agent2Fa;

class Agent2FaService
{
    /**
     * 更新代理两步验证状态
     * @param Agent $agent
     * @param int $status
     * @return string|null 错误 msg
     */
    public static function updateStatus(Agent $agent, int $status): ?string
    {
        $agentNo = $agent->agent_no;
        $agent2Fa = Agent2Fa::findByAgentNo($agentNo);
        if (is_null($agent2Fa)) {
            if (Agent2Fa::STATUS_DISABLE === $status) {
                return sprintf('代理 %s 的两步验证未启用，请先启用两步验证', $agentNo);
            }
            $agent2Fa = new Agent2Fa();
            $agent2Fa->agent_no = $agentNo;
            $agent2Fa->status = Agent2Fa::STATUS_ENABLE;
            $agent2Fa->secret = TwoFactorAuth::genSecret();
            return $agent2Fa->save() ? null : sprintf('代理 %s 两步验证更新失败', $agentNo);
        } elseif ($agent2Fa->status === $status) {
            // 状态未改变
            return null;
        }
        $agent2Fa->status = $status;
        return $agent2Fa->save() ? null : sprintf('代理 %s 两步验证更新失败', $agentNo);
    }

    /**
     * @param Agent $agent
     * @return string|null 密钥
     */
    public static function getQrCode(Agent $agent): ?string
    {
        $agent2Fa = Agent2Fa::findByAgentNo($agent->agent_no);
        if (is_null($agent2Fa)) {
            return null;
        } elseif (Agent2Fa::STATUS_DISABLE === $agent2Fa->status) {
            return null;
        }
        return TwoFactorAuth::getQrCode($agent2Fa->secret, $agent->mobile, config('app.app_name'));
    }

    /**
     * @param Agent $agent
     * @return string|null 错误 msg
     */
    public static function resetSecret(Agent $agent): ?string
    {
        $agent2Fa = Agent2Fa::findByAgentNo($agent->agent_no);
        if (is_null($agent2Fa)) {
            return sprintf('代理 %s 没有开启两步验证，无法重置', $agent->agent_no);
        } elseif (Agent2Fa::STATUS_DISABLE === $agent2Fa->status) {
            return sprintf('代理 %s 的两步验证未启用，无法重置', $agent->agent_no);
        }
        $agent2Fa->secret = TwoFactorAuth::genSecret();
        return $agent2Fa->save() ? null : sprintf('代理 %s 两步验证重置失败', $agent->agent_no);
    }

    /**
     * 验证代理两步验证码
     * @param Agent $agent
     * @param string $code
     * @return string|null 错误 msg
     */
    public static function verifyCode(Agent $agent, string $code): ?string
    {
        if (6 !== strlen($code)) {
            return '验证码长度错误，可能短信验证码';
        }
        $agent2Fa = Agent2Fa::findByAgentNo($agent->agent_no);
        if (is_null($agent2Fa)) {
            return sprintf('代理 %s 没有开启两步验证，无法完成验证', $agent->agent_no);
        } elseif (Agent2Fa::STATUS_DISABLE === $agent2Fa->status) {
            return sprintf('代理 %s 的两步验证未启用，无法完成验证', $agent->agent_no);
        }
        $agent2Fa->verify_count++;
        $agent2Fa->save();
        return TwoFactorAuth::verify($agent2Fa->secret, $code) ? null : sprintf('代理 %s 两步验证验证码 %s 错误', $agent->agent_no, $code);
    }
}
